/*
 * Package il.ac.biu.cs.grossmm.test.test1
 * File Publisher.java
 * Created on Aug 15, 2006
 *
 */
package il.ac.biu.cs.grossmm.tests.test1;

import static il.ac.biu.cs.grossmm.api.data.NodeTypeByInterface.nodeType;
import static il.ac.biu.cs.grossmm.api.keys.KeyFactory.entry;
import static il.ac.biu.cs.grossmm.api.keys.KeyFactory.key;
import static il.ac.biu.cs.grossmm.api.keys.PatternFactory.mandatory;
import static il.ac.biu.cs.grossmm.api.keys.PatternFactory.pattern;
import il.ac.biu.cs.grossmm.api.data.Node;
import il.ac.biu.cs.grossmm.api.data.Root;
import il.ac.biu.cs.grossmm.api.flow.ActiveDataManager;
import il.ac.biu.cs.grossmm.api.flow.NodeManipulator;
import il.ac.biu.cs.grossmm.api.flow.PublicationPoint;
import il.ac.biu.cs.grossmm.api.flow.QueryProcessor;
import il.ac.biu.cs.grossmm.api.keys.Key;
import il.ac.biu.cs.grossmm.api.keys.KeyPattern;
import il.ac.biu.cs.grossmm.api.presence.BaseVocabulary;
import il.ac.biu.cs.grossmm.api.presence.ResourceType;
import il.ac.biu.cs.grossmm.api.server.Component;
import il.ac.biu.cs.grossmm.api.server.ComponentManager;
import il.ac.biu.cs.grossmm.api.server.ServiceManager;
import il.ac.biu.cs.grossmm.api.server.Service;

import java.util.Set;

import org.apache.log4j.Logger;

public class Publisher extends Thread implements Component, Service {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(Publisher.class);

	ActiveDataManager adm;

	PublicationPoint<Pidf> presencePoint;

	private ServiceManager serviceManager;

	public Publisher()
	{
		super("Publisher");
	}

	public void setComponentManager(ComponentManager container)
		throws Exception
	{
		adm =
			(ActiveDataManager) container.getComponent(ActiveDataManager.class);

		KeyPattern pattern =
			pattern(String.class, mandatory(BaseVocabulary.RESOURCE_TYPE,
				ResourceType.PRESENCE));

		presencePoint =
			adm.createPublicationPoint(pattern, nodeType(Pidf.class), true, "presence");
	}

	public void start(ServiceManager serviceManager) throws Exception
	{
		if (logger.isDebugEnabled()) {
			logger.debug("start() - start");
		}

		this.serviceManager = serviceManager;
		start();

		if (logger.isDebugEnabled()) {
			logger.debug("start(ServiceManager) - end");
		}
	}

	public void stop(Exception exception)
	{
		if (logger.isDebugEnabled()) {
			logger.debug("stop() - start");
		}

		interrupt();

		try {
			join();
		} catch (InterruptedException e) {
			logger.warn("stop(Exception) - exception ignored", e);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("stop(Exception) - end");
		}
	}

	public void terminated(Object serviceHint, Exception e)
	{
		stop(null);
	}

	public void aborted(Object hint, Exception e)
	{
		stop(null);
	}

	@Override
	public void run()
	{

		try {
			sleep(500);
		} catch (InterruptedException e) {
			return;
		}

		Key key =
			key("pres:Alice@example.com", entry(BaseVocabulary.RESOURCE_TYPE,
				ResourceType.PRESENCE));

		Root<Pidf> pidf;
		Node<Tuple> tuple;
		NodeManipulator man;
		try {
			logger.debug("Creating pidf for Alice");
			pidf = presencePoint.createNode(key, true);

			logger.debug("Locking pidf");
			man = presencePoint.writeLock(pidf);

			QueryProcessor<Pidf> p = new QueryProcessor<Pidf>(man, pidf);

			if (!p.contains(Pidf.TUPLES, Tuple.ID, "06a6ef001")) {
				if (logger.isDebugEnabled()) {
					logger.debug("Does NOT contain 06a6ef001");
				}
				man.setValue(pidf, Pidf.ENTITY, "Alice");
				tuple = man.createSubnode(pidf, Pidf.TUPLES);
				man.setValue(tuple, Tuple.ID, "06a6ef001");
				man.setValue(tuple, Tuple.BASIC_STATUS, true);
				man.setValue(tuple, Tuple.CONTACT, "im:alice@example.com");
			} else if (logger.isDebugEnabled()) {
				logger.debug("Does contain 06a6ef001");
			}

			logger.debug("Unlocking pidf");
			presencePoint.writeUnlock(pidf);
			logger.debug("Unlocked pidf");

			key =
				key("pres:Bob@example.com", entry(BaseVocabulary.RESOURCE_TYPE,
					ResourceType.PRESENCE));

			logger.debug("Creating pidf for Bob");
			pidf = presencePoint.createNode(key, true);

			man = presencePoint.writeLock(pidf);

			man.setValue(pidf, Pidf.ENTITY, "Bob");
			tuple = man.createSubnode(pidf, Pidf.TUPLES);
			man.setValue(tuple, Tuple.BASIC_STATUS, false);
			man.setValue(tuple, Tuple.CONTACT, "im:bob@example.com");

			logger.debug("Unlocking pidf");
			presencePoint.writeUnlock(pidf);
			logger.debug("Unlocked pidf");

			try {
				sleep(1500);
			} catch (InterruptedException e) {
				return;
			}

			key =
				key("pres:Alice@example.com", entry(BaseVocabulary.RESOURCE_TYPE,
					ResourceType.PRESENCE));

			logger.debug("Getting pidf for Alice");
			pidf = presencePoint.getRoot(key);

			man = presencePoint.writeLock(pidf);
			Set<? extends Node<Tuple>> tuples =
				man.getSubnodes(pidf, Pidf.TUPLES);

			tuple = tuples.iterator().next();
			man.setValue(tuple, Tuple.BASIC_STATUS, false);

			Node<Tuple> t0 = man.createSubnode(pidf, Pidf.TUPLES);
			man.setValue(t0, Tuple.ID, "76423412");
			man.setValue(t0, Tuple.CONTACT, "icq:9234676");
			man.setValue(t0, Tuple.BASIC_STATUS, false);

			Node<Tuple> t1 = man.createSubnode(pidf, Pidf.TUPLES);
			man.setValue(t1, Tuple.ID, "7000002");
			man.setValue(t1, Tuple.CONTACT, "mailto:x@y.com");
			man.setValue(t1, Tuple.BASIC_STATUS, true);

			logger.debug("Unlocking pidf");
			presencePoint.writeUnlock(pidf);
			logger.debug("Unlocked pidf");

			try {
				sleep(1500);
			} catch (InterruptedException e) {
				return;
			}

			logger.debug("=======================");

			man = presencePoint.writeLock(pidf);

			man.removeSubnode(t0);

			logger.debug("Unlocking pidf");
			presencePoint.writeUnlock(pidf);
			logger.debug("Unlocked pidf");

		} catch (Exception e) {
			e.printStackTrace();
			serviceManager.terminated(e);
		}

	}

}
